/* libfake437 - a library for the rendering of code page 437 `graphics'
 * Copyright (C) 2008, 2009 Jack Kelly <endgame.dos@gmail.com>
 *
 * This library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include <SDL.h>
#include "fake437/types.h"
#include "fake437/primitive.h"
#include "fake437/surface.h"

F437Surface* f437_surface_new(SDL_Surface* surface) {
  F437Surface* result = malloc(sizeof(*result));
  if(result == NULL) abort();
  result->surface = surface;
  result->left = (surface->w % F437_CHAR_WIDTH) / 2;
  result->top = (surface->h % F437_CHAR_HEIGHT) / 2;
  result->width = surface->w / F437_CHAR_WIDTH;
  result->height = surface->h / F437_CHAR_HEIGHT;
  return result;
}

void f437_surface_free(F437Surface* surface) {
  free(surface);
}

void f437_surface_put_char(F437Surface* surface, int left, int top, int ch,
                           const SDL_Color* fg, const SDL_Color* bg) {
  assert(surface != NULL);
  assert(surface->surface != NULL);
  assert(left < surface->width);
  assert(top < surface->height);
  f437_put_char(surface->surface,
                surface->left + F437_CHAR_WIDTH * left,
                surface->top + F437_CHAR_HEIGHT * top,
                ch, fg, bg);
}

void f437_surface_put_rect(F437Surface* surface, int left, int top,
                           int width, int height, int ch,
                           const SDL_Color* fg, const SDL_Color* bg) {
  int x_char;
  int y_char;
  assert(surface != NULL);
  assert(surface->surface != NULL);
  assert(width >= 0);
  assert(height >= 0);
  assert(left + width <= surface->width);
  assert(top + height <= surface->height);
  if (SDL_MUSTLOCK(surface->surface)) SDL_LockSurface(surface->surface);
  for (y_char = 0 ; y_char < height ; y_char++) {
    for (x_char = 0 ; x_char < width ; x_char++) {
      f437_surface_put_char(surface, left + x_char, top + y_char, ch, fg, bg);
    }
  }
  if (SDL_MUSTLOCK(surface->surface)) SDL_UnlockSurface(surface->surface);
}

void f437_surface_put_string(F437Surface *surface, int left, int top,
                             const char *string,
                             const SDL_Color* fg, const SDL_Color* bg) {
  const char* c;
  int i = 0;
  assert(surface != NULL);
  assert(surface->surface != NULL);
  assert(left >= 0);
  assert(top >= 0);
  assert(top < surface->width);
  if (SDL_MUSTLOCK(surface->surface)) SDL_LockSurface(surface->surface);
  for (c = string ; *c ; c++, i++) {
    if (left + i > surface->width) break;
    f437_surface_put_char(surface, left + i, top, *c, fg, bg);
  }
  if (SDL_MUSTLOCK(surface->surface)) SDL_UnlockSurface(surface->surface);
}
